#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mount.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <cutils/sockets.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/select.h>
#include <sys/types.h>
#include <pthread.h>
#include <dlfcn.h>
#ifndef TEMP_FAILURE_RETRY
/* Used to retry syscalls that can return EINTR. */
#define TEMP_FAILURE_RETRY(exp) ({         \
        typeof (exp) _rc;                      \
        do {                                   \
        _rc = (exp);                       \
        } while (_rc == -1 && errno == EINTR); \
        _rc; })
#endif


static __inline__  int  adb_read(int  fd, void*  buf, size_t  len)
{
        return TEMP_FAILURE_RETRY( read( fd, buf, len ) );
}

static __inline__ int  adb_close(int fd)
{
        return close(fd);
}

static __inline__ int  unix_open(const char*  path, int options,...)
{
    if ((options & O_CREAT) == 0)
    {
        return  open(path, options);
    }
    else
    {
        int      mode;
        va_list  args; 
        va_start( args, options );
        mode = va_arg( args, int );
        va_end( args );
        return open(path, options, mode);
    }
}   

/* Returns the device used to mount a directory in /proc/mounts */
static char *find_mount(const char *dir)
{
    int fd;
    int res;
    int size;
    char *token = NULL;
    const char delims[] = "\n";
    char buf[4096];

    fd = unix_open("/proc/mounts", O_RDONLY);
    if (fd < 0)
        return NULL;

    buf[sizeof(buf) - 1] = '\0';
    size = adb_read(fd, buf, sizeof(buf) - 1);
    adb_close(fd);

    token = strtok(buf, delims);

    while (token) {
        char mount_dev[256];
        char mount_dir[256];
        int mount_freq;
        int mount_passno;

        res = sscanf(token, "%255s %255s %*s %*s %d %d\n",
                mount_dev, mount_dir, &mount_freq, &mount_passno);
        mount_dev[255] = 0;
        mount_dir[255] = 0;
        if (res == 4 && (strcmp(dir, mount_dir) == 0))
            return strdup(mount_dev);

        token = strtok(NULL, delims);
    }
    return NULL;
}


int remount_system(unsigned long flags) {
    char *dev;
    int fd;
    int ret;
    int OFF = 0;

    dev = find_mount("/system");
    if (!dev)
        return -1; 

    fd = unix_open(dev, O_RDONLY);
    if (fd < 0)
        return -1; 

    ioctl(fd, BLKROSET, &OFF);
    adb_close(fd);
    ret = mount(dev, "/system", "none", flags, NULL);
    free(dev);

    return ret;
}


int systemCmd(char* path) {
    FILE * fp = fopen(path, "r");
    if (fp == NULL)
        return -1; 
    char buf[255];
    int ret = -1, i = 0;
    char *p;
    while (fgets(buf, sizeof(buf), fp)) {
        if (strchr(buf, '#'))
            continue;
        p = strstr(buf, "cmd:");
        if (p) {
            p += 4;
            buf[strlen(buf)+1] = '\0';
            ALOGE("cmd buf=%s", p);
            ret = system(p);
        }
    }   
    fclose(fp);
    return ret;
}
#define COPY_SIZE (5*1024*1024)
void copy_file(char *dest, char *src) {
    FILE *f_src, *f_dest;
    char *buf;
    int size;

    f_src = fopen(src, "rb");
    if (!f_src) {
        SLOGE("open src file err[%s]", strerror(errno));
        return ;
    }
    f_dest = fopen(dest, "w+");
    if (!f_dest) {
        SLOGE("open dest file err[%s]", strerror(errno));
        return ;
    }
    chmod(dest, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

    buf = (char *)malloc(COPY_SIZE);
    if (!buf) {
        SLOGE("malloc buf err[%s]", strerror(errno));
        return ;
    }
    size = fread(buf, 1, COPY_SIZE, f_src);
    while (size != 0) {
        fwrite(buf, size, 1, f_dest);
        size = fread(buf, 1, COPY_SIZE, f_src);
    }

    free(buf);
    fclose(f_src);
    fclose(f_dest);
    system("sync");

}
